#include "event-internal.h"
#include "include/event_struct.h"
#include "include/util.h"
#include <event2/event.h>
#include <string.h>
static int evmap_make_space(struct event_signal_map *map, int slot, int msize);
static void  evmap_io_init(struct evmap_io *entry);
#define GET_SIGNAL_SLOT(x, map, slot, type) (x) = (struct type *)((map)->entries[slot])
/* As GET_SLOT, but construct the entry for 'slot' if it is not present,
   by allocating enough memory for a 'struct type', and initializing the new
   value by calling the function 'ctor' on it.  Makes the function
   return -1 on allocation failure.
 */
#define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len)                                                 \
    do                                                                                                                 \
    {                                                                                                                  \
        if ((map)->entries[slot] == NULL)                                                                              \
        {                                                                                                              \
            (map)->entries[slot] = calloc(1, sizeof(struct type) + fdinfo_len);                                     \
            if (((map)->entries[slot] == NULL))                                                         \
                return (-1);                                                                                           \
            (ctor)((struct type *)(map)->entries[slot]);                                                               \
        }                                                                                                              \
        (x) = (struct type *)((map)->entries[slot]);                                                                   \
    } while (0)

#define GET_IO_SLOT(x, map, slot, type) GET_SIGNAL_SLOT(x, map, slot, type)
#define GET_IO_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len)                                                     \
    GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len)

int evmap_io_add(struct event_base *base, evutil_socket_t fd, struct event *ev)
{
    // 获得event_base的后端I/O复用机制实例
    const struct eventop *evsel = base->evsel;
    // 获得event_base中文件描述符与I/O事件队列的映射表
    struct event_io_map *io = &base->io;
    // fd参数对应的IO事件队列
    struct evmap_io *ctx = NULL;
    int nread, nwrite, retval = 0;
    short res = 0,old = 0;
    struct event *old_ev;

    if (fd < 0)
        return 0;
    // IO事件队列数组 io.entries中 每个文件描述符占用一项 如果fd大于当前数组的大小 则增加数组的大小
    // (扩大后数组的容量要大于fd)
    if (fd >= io->nentries)
    {
        if (evmap_make_space(io, fd, sizeof(struct evmap_io)) == 1)
            return -1;
    }

    GET_SIGNAL_SLOT_AND_CTOR(ctx, io, fd, evmap_io, evmap_io_init, evsel->fdinfo_len);
    nread = ctx->nread;
    nwrite = ctx->nwrite;
    if(nread)
        old|=EV_READ;
        if(nwrite)
        old |=EV_WRITE;
}

static int evmap_make_space(struct event_signal_map *map, int slot, int msize)
{
    if (map->nentries <= slot)
    {
        int nentries = map->nentries ? map->nentries : 32;
        void **tmp;

        while (nentries <= slot)
            nentries <<= 1;

        tmp = (void **)realloc(map->entries, nentries * msize);
        if (tmp == NULL)
            return (-1);

        memset(&tmp[map->nentries], 0, (nentries - map->nentries) * msize);

        map->nentries = nentries;
        map->entries = tmp;
    }

    return (0);
}

static void evmap_io_init(struct evmap_io *entry)
{
    TAILQ_INIT(&entry->events);
    entry->nread = 0;
    entry->nwrite = 0;
}
